<?php


namespace app\common\model;


use think\Exception;

class NewModule extends BaseModel
{

    public $newCode = [];//提取的新代码
    public $coverList = [];//选择覆盖的文件
    //命名空间
    public static $namespaces = [
        'app\admin\controller',
        'app\common\model',
        'app\admin\view',

        //api接口相关代码生成位置
        'app\api\controller',
        'app\api\services',
        'app\api\validate',
    ];

    //模板文件目录
    public static $file_tpl = ROOT_PATH.DS.'app\common\tpl\new_module\\';

    //系统表  不允许生成CURD
    public static $systemTable = [
        'admin',
        'admin_log',
        'web_log',
        'auth_group',
        'auth_group_access',
        'auth_rule',
        'new_module',
        'upload_files',
        'payment',
        'payment_refund',
    ];

    //可选编辑框内容
    // field_type 1 文本 2 开关 3 单选 4 复选 5下拉 6单图 7 多图 8富文本 9 锁定
    public static $fieldType = [
        '1'=>'文本框',
        '2'=>'开关按钮',
        '3'=>'单选框',
        '4'=>'复选框',
        '5'=>'下拉列表框',
        '6'=>'单图上传',
        '7'=>'多图上传',
        '8'=>'富文本框',
        '9'=>'锁定框',
    ];

    function getNameTextAttr($value,$data){
        if($data['is_output']==1){
            return $data['name'].'<i class="layui-icon layui-icon-ok cgreen mal5" title="已生成" ></i>';
        }else{
            return $data['name'];
        }
    }

    //设置列表查询条件
    function getListWhere($model,$param=[]){
        if(empty($param)){
            return [];
        }

        $where = [];
        //创建时间查询
        if( $param['create_time']!='' ) {
            $create_time = explode('至',$param['create_time']);
            $date_time = [
                strtotime($create_time[0]),
                strtotime($create_time[1].' 23:59:59'),
            ];
            $model->whereBetween('create_time',$date_time);
        }

        if(isset($param['is_show']) && $param['is_show']!=''){
            $where['is_show'] = $param['is_show'];
        }

        //检索查询
        if($param['search_key']){
            $model->whereLike("name|table_name","%{$param['search_key']}%");
        }
        if($where){
            $model->where($where);
        }
    }

    //数据查询
    function getList($param){
        $order = $param['order']?:'id desc';
        $model = $this->order($order);
        $this->getListWhere($model,$param);
        $list = $model->paginate($param['limit']);
        return $list;
    }


    //获取
    function getInfo($id){
        $data = $this->where('id',$id)->find();
        //字段解析
        $fieldArr = json_decode($data['field'],1);
        $fieldTextArr = [];
        if($data['field_text']){
            $fieldTextArr = json_decode($data['field_text'],1);
        }

        $reData = [];
        foreach ($fieldArr as $k=>$v){
            $isNew = true;
            foreach ($fieldTextArr as $ks=>$vs){
                if($v['field']==$vs['field']){
                    $reData[] = [
                        'id'=>$k+1,
                        'field'=>$v['field'],
                        'type'=>$v['type'],
                        'name'=>$vs['name']?:$v['field'],//字段标题
                        'field_type'=>$vs['field_type']?:1,//字段类型
                        'field_default'=>$vs['field_default'],//字段默认值
                        'show_list'=>$vs['show_list'],//列表是否显示
                        'is_edit'=>$vs['is_edit'],//是否参与编辑
                        'is_time'=>$vs['is_time'],//是否是时间字段
                        'column_comment'=>$v['column_comment'],//字段注释
                    ];
                    $isNew = false;
                    break;
                }
            }
            if($isNew){
                $reData[] = [
                    'id'=>$k+1,
                    'field'=>$v['field'],
                    'type'=>$v['type'],
                    'name'=>$v['field'],//字段标题
                    'field_type'=>1,//字段类型
                    'field_default'=>'',//字段默认值
                    'show_list'=>1,//列表是否显示
                    'is_edit'=>1,//是否参与编辑
                    'is_time'=>0,//是否是时间字段
                    'column_comment'=>$v['column_comment'],//字段注释
                ];
            }
        }

        return $reData;

    }

    /**
     * 保存模块信息
     * @param $data
     */
    public function saveTable($data){
        if(empty($data['id'])){
            throw new Exception('请输入id');
        }
        $moduleInfo = $this->where('id',$data['id'])->find();
        if(empty($moduleInfo)){
            throw new Exception('模块信息不存在，请先同步数据库信息！');
        }
        //是否删除原有模块
        $isDel = $data['isdel'];
        if($moduleInfo['is_output']==1 && $moduleInfo['file_name'] && $data['name'] && $data['file_name'] && $moduleInfo['file_name']!=$data['file_name']){
            //如果已经有文件名存在了  并且 和修改的文件名不同
            if(!$isDel){
                throw new Exception('您修改了文件名<br/>是否要移除删除旧模块？<br/>旧文件名：<span class="cred">['.$moduleInfo['file_name'].']</span>',100);
            }
        }

        //整理列表数据
        $tableData = $data['tableData'];
        //数据处理 效验
        foreach ($tableData as $k=>$v){
            if(in_array($v['field_type'],[1,6,7,8])){
                $tableData[$k]['field_default'] = '';
            }else{
                //等于没值
                if($v['field_default']=='{}'){
                    $tableData[$k]['field_default'] = '';
                }else{
                    //解析值
                    $tableData[$k]['field_default'] = json_decode($v['field_default'],1);
                }
                $count = count($tableData[$k]['field_default']);
                if(in_array($v['field_type'],[2])){
                    if($count>0 && $count!=2){
                        throw new Exception("字段：[{$v['name']}]，默认值需要有2个参数");
                    }else if($count==0){
                        $tableData[$k]['field_default'] = [1=>'正常',0=>'禁用'];
                    }else{
                        //修复某个问题
                        if($tableData[$k]['field_default'][0] && $tableData[$k]['field_default'][1]){
                            $tableData[$k]['field_default'] = [
                                '1'=>$tableData[$k]['field_default'][1],
                                '0'=>$tableData[$k]['field_default'][0],
                            ];
                        }
                    }
                }
                if($v['field_type']==9){
                    if($count>0 && $count!=1){
                        throw new Exception("字段：[{$v['name']}]，默认值需要有1个参数");
                    }else if($count==0){
                        $tableData[$k]['field_default'] = [1=>'锁定'];
                    }else{
                        //修复某个问题
                        if($tableData[$k]['field_default'][0] && $tableData[$k]['field_default'][1]){
                            $tableData[$k]['field_default'] = [
                                '1'=>$tableData[$k]['field_default'][1],
                                '0'=>$tableData[$k]['field_default'][0],
                            ];
                        }
                    }
                }
                if(in_array($v['field_type'],[3,4,5]) && $count==0){
                    throw new Exception("字段：[{$v['name']}]，默认值至少需要有1个参数");
                }
                if($tableData[$k]['field_default']){
                    $tableData[$k]['field_default'] = json_encode($tableData[$k]['field_default'],JSON_UNESCAPED_UNICODE);
                }
            }
        }
        if($moduleInfo['file_name']){
            //文件名不能重复
            $repeatWhere = [
                ['id','<>',$data['id']],
                ['file_name','=',$data['file_name']]
            ];
            if($this->where($repeatWhere)->count()){
                throw new Exception("文件名不能和现有模块文件名重复");
            }
        }
        $upData = ['up_time'=>time()];
        if(!empty($data['name'])){
            $upData = [
                'name'=>$data['name'],
                'file_name'=>$data['file_name'],
                'is_edit_new'=>$data['is_edit_new'],
                'field_text'=>json_encode($tableData,302),
            ];
            if($data['file_name']){
                //检查模型文件 是否和现有文件冲突
                $fileAll = $this->getFilePath($data['file_name']);
                if($this->isFileExistence($fileAll)){
                    if($moduleInfo['is_output']==0){
                        throw new Exception("文件[<span class='cred'>{$data['file_name']}</span>]已经存在，请修改文件名");
                    }else if($moduleInfo['file_name']!=$data['file_name']){
                        throw new Exception("文件[<span class='cred'>{$data['file_name']}</span>]已经存在，请修改文件名");
                    }
                }

                if($upData['file_name']!=$moduleInfo['file_name'] ){
                    $upData['is_output'] = 0;//修改了文件名  默认未生成
                }
            }
        }
        if(isset($data['status'])){
            $upData['status'] = $data['status'];
        }
        if(isset($data['is_show'])){
            $upData['is_show'] = $data['is_show'];
        }
        if(isset($data['is_model'])){
            $upData['is_model'] = $data['is_model'];
        }


        $res = $this->where('id',$data['id'])->update($upData);
        return $res;
    }

    //传入表名  得到默认的 文件名
    static function getFileName($table_name){
        $config = config('database');
        $config = $config['connections'][$config['default']];
        //移除表前缀
        $table_name = str_replace($config['prefix'],'',$table_name);
        $arr = explode('_',$table_name);
        return join('',array_map(function($a){return ucfirst($a);},$arr));
    }

    //移除已经生成的模块文件
    public function deleteModule($id,$isApi){
        $moduleModel = $this->where('id',$id)->find();
        if(!$moduleModel){
            throw new Exception("模块配置信息不存在，请检查",100);
        }
        if(!$isApi && $moduleModel->is_output!=1){
            throw new Exception("尚未生成模块，无需删除！",100);
        }
        if($isApi && $moduleModel->is_output_api!=1){
            throw new Exception("尚未生成api模块，无需删除！",100);
        }

        //获取生成的文件路径
        $moduleInfo = $moduleModel->toArray();
        if(!$isApi){
            $fileAll = $this->getFilePath($moduleInfo['file_name']);
            //有改动的模块 禁止移除
            $this->isAddFunction($fileAll);
        }else{
            $fileAll = $this->getFilePathApi($moduleInfo['file_name']);
            //有改动的模块 禁止移除
            $this->isAddFunctionApi($fileAll);
        }
        //移除文件
        foreach ($fileAll as $key =>$item){
            if(is_array($item)){
                foreach ($item as $file){
                    if(file_exists($file)){
                        unlink($file);
                    }
                }
            }else if($key == 'html_file_name'){
                //移除模板文件夹
                $file = ROOT_PATH.self::$namespaces[2].DS.$item;
                //循环移除模板文件夹目录
                deldir($file);
            }
        }

        //移除路由
        !$isApi && $this->delRoute($moduleInfo);

        //更新数据
        if(!$isApi){
            $moduleModel->where(['id'=>$id])->update(['is_output'=>0]);
        }else{
            $moduleModel->where(['id'=>$id])->update(['is_output_api'=>0]);
        }
        return $moduleInfo;
    }

    /**
     * 生成模块功能文件
     * @param $id  模型信息id
     * @param $isCover 是否覆盖生成
     * @param $isApi 真 生成api接口代码  假 生成后台curd代码
     */
    function generate($id,$isCover=false,$isApi=false,$coverList=[]){
        $this->coverList = $coverList;
        $moduleModel = $this->where('id',$id)->find();
        if(!$moduleModel){
            throw new Exception("模块配置信息不存在，请检查",100);
        }
        if(!$moduleModel->name){
            throw new Exception("请先指定模块的模块名，才能生成模块",100);
        }
        if(!$moduleModel->file_name){
            throw new Exception("请先指定模块的文件名，才能生成模块",100);
        }

        $moduleInfo = $moduleModel->toArray();
        //获取生成的文件路径
        if(!$isApi){
            $fileAll = $this->getFilePath($moduleInfo['file_name']);
        }else{
            $fileAll = $this->getFilePathApi($moduleInfo['file_name']);
        }

        //检查模块是否存在  存在就直接返回
        if(!$isCover && $this->isFileExistence($fileAll)){
            throw new Exception("模块[{$moduleInfo['name']}]已经存在，是否要覆盖生成？",101);
        }
        //如果是覆盖生成 那么检查模型 和 控制器 是否有新增方法 如果有 就不允许覆盖生成
        if($isCover){
            if(!$isApi){
                //新的代码
                $this->newCode = $this->isAddFunction($fileAll,true);
            }else{
                //新的代码
                $this->newCode = $this->isAddFunctionApi($fileAll,true);
            }
        }

        //解析信息
        $moduleInfo['field_text'] = json_decode($moduleInfo['field_text'],1);
        //解析字段的默认值
        foreach ($moduleInfo['field_text'] as $k=>$v){
            if($v['field_default'] && $v['field_default']!='null' && $field_default = json_decode($v['field_default'],1)){
                $moduleInfo['field_text'][$k]['field_default'] = $field_default;
            }else{
                $v['field_default'] = '';
            }
        }
        $this->OutPutFileStart($moduleInfo,$fileAll,$isApi);
        return $moduleInfo;
    }

    //开始生成文件
    private function OutPutFileStart($moduleInfo,$fileAll,$isApi){
        $updata = ['output_time' => time()];

        if($isApi){
            $this->outputFileApi($moduleInfo,$fileAll);
            //生成前端接口api文件
            $updata['is_output_api'] = 1;
        }else{
            //后台curd生成
            //写出模块文件
            $this->outputFile($moduleInfo,$fileAll);
            // 添加or移除 路由管理
            if($moduleInfo['status']==1 && $moduleInfo['is_model']!=1){
                $this->addRoute($moduleInfo);
            }else{
                $this->delRoute($moduleInfo);
            }
            //已经生成后端模块文件
            $updata['is_output'] = 1;
        }
        //更新状态
        (new self())->where('id',$moduleInfo['id'])->update($updata);
    }


    //检查类 是否有手动新增方法
    private function isAddFunction($fileAll,$isExtract=false){
        $extract = [];
        $controller = $fileAll['controller'][0];
        $model = $fileAll['model'][0];
        //默认的控制器方法
        $controllerArr = ['Index','edit','delete','exportData'];
        //默认的模型方法
        $modelArr = ['getListWhere','getList','getExport','saveData'];
        $controllerAdd = $this->isAddFunctionItem($controller,$controllerArr,"app\admin\controller\\");
        if(!empty($controllerAdd['function']) || !empty($controllerAdd['proper'])){
            if($isExtract){
                $extract['controller'] = $this->extractNewCode($controller,$controllerAdd);
            }else{
                if(empty($controllerAdd['function'])){
                    throw new Exception("当前控制器有新增".count($controllerAdd['proper'])."个属性冲突，无法移除代码，请手动处理！<br/>新增属性：".join(',',$controllerAdd['proper']));
                }else{
                    throw new Exception("当前控制器有新增".count($controllerAdd['function'])."个方法冲突，无法移除代码，请手动处理！<br/>新增方法：".join(',',$controllerAdd['function']));
                }
            }
        }
        $modelAdd = $this->isAddFunctionItem($model,$modelArr,"app\common\model\\");
//        dump($isExtract);exit;
        if(!empty($modelAdd['function']) || !empty($modelAdd['proper'])){
            if($isExtract){
                $extract['model'] = $this->extractNewCode($model,$modelAdd);
            }else{
                if(empty($modelAdd['function'])){
                    throw new Exception("当前模型有新增".count($modelAdd['proper'])."个属性冲突，无法移除代码，请手动处理！<br/>新增属性：".join(',',$modelAdd['proper']));
                }else{
                    throw new Exception("当前模型有新增".count($modelAdd['function'])."个方法冲突，无法移除代码，请手动处理！<br/>新增方法：".join(',',$modelAdd['function']));
                }
            }
        }
//        dump($extract);exit;
        return $extract;
    }



    //检查类 是否有手动新增方法
    private function isAddFunctionApi($fileAll,$isExtract=false){
        $extract = [];
        $controller = $fileAll['controller'][0];
        $service = $fileAll['service'][0];
        //默认的控制器方法
        $controllerArr = ['lists','detail','update','delete','add'];
        //默认的服务方法
        $serviceArr = ['getList','getDetail','delete','update','add','getListWhere'];
        $controllerAdd = $this->isAddFunctionItem($controller,$controllerArr,"app\api\controller\\");
        if(!empty($controllerAdd['function']) || !empty($controllerAdd['proper'])){
            if($isExtract){
                $extract['controller'] = $this->extractNewCode($controller,$controllerAdd);
            }else{
                if(empty($controllerAdd['function'])){
                    throw new Exception("当前api控制器有新增".count($controllerAdd['proper'])."个属性冲突，无法移除代码，请手动处理！<br/>新增属性：".join(',',$controllerAdd['proper']));
                }else{
                    throw new Exception("当前api控制器有新增".count($controllerAdd['function'])."个方法冲突，无法移除代码，请手动处理！<br/>新增方法：".join(',',$controllerAdd['function']));
                }
            }
        }
        $serviceAdd = $this->isAddFunctionItem($service,$serviceArr,"app\api\services\\");
        if(!empty($serviceAdd['function']) || !empty($serviceAdd['proper'])){
            if($isExtract){
                $extract['service'] = $this->extractNewCode($service,$serviceAdd);
            }else{
                if(empty($serviceAdd['function'])){
                    throw new Exception("当前api服务有新增".count($serviceAdd['proper'])."个属性冲突，无法移除代码，请手动处理！<br/>新增属性：".join(',',$serviceAdd['proper']));
                }else{
                    throw new Exception("当前api服务有新增".count($serviceAdd['function'])."个方法冲突，无法移除代码，请手动处理！<br/>新增方法：".join(',',$serviceAdd['function']));
                }
            }
        }
//        dump($extract);exit;
        return $extract;
    }

    //在某个类文件中 提取新方法代码
    private function extractNewCode($path,$functionAll){
        $content_text = file_get_contents($path);
        $maxLeng = strlen($content_text);
        $new_function = [];

        $actionAll = $functionAll['function'];//方法列表
        $properAll = $functionAll['proper'];//属性列表

        $suffix = [' ','=',';'];
        //属性代码提取
        foreach ($properAll as $item){
//            $pattern = '#[\/\*\S]*[\r\n]*[\w\s]*\\$'.$item.'#';
            $pattern = '#[\w\s]+\\$'.$item.'#';

//            $pattern = "#function {$item}\(.*\)({([^{}]+|(?R))*})#";
            preg_match_all($pattern,$content_text,$arr);
            //标记文本  从标记文本开始  寻找;结束标志
            $stamp = $arr[0][0];
//            dump($stamp);exit;
            $start = $stamp_index = 0;
            $item_content = '';

            $start_index = $end_index = 0;
            //确定唯一位置
            foreach ($suffix as $suffix_item){
                if($stamp_index){
                    continue;
                }
                $stamp_index = strpos($content_text,$stamp.$suffix_item);
            }
            $stamp_index_item = $stamp_index;
            //向前搜寻注释
            for($i=$stamp_index;$i>0;$i--){
                //以 {}  作为结束标志
                $text = $content_text[$i];
                if($text == '{' || $text == '}' || $text == ';'){
                    $start_index = $i+1;
                    break;
                }
            }

            //向后搜寻
            for(;$stamp_index_item<$maxLeng;$stamp_index_item++){
                if(!$start && $content_text[$stamp_index_item]==';'){
                    $start=2;
                }
                if($start==2 && $content_text[$stamp_index_item]=="\n"){
                    $end_index = $stamp_index_item;
                    break;
                }
            }
            $item_content = substr($content_text,$start_index,$end_index-$start_index+1);
            $item_content = trim($item_content,"\r\n");
//            dump($start);
//            dump($item_content);exit;
            $new_function[] = $item_content;
        }

        //方法代码提取
        foreach ($actionAll as $item){
            $pattern = "#[\/\*\S ]*[\r\n]*[\w\s]*function {$item}\(.*\)#";
//            $pattern = "#function {$item}\(.*\)({([^{}]+|(?R))*})#";
            preg_match_all($pattern,$content_text,$arr);
//            dump($arr[0]);
            //标记文本
            $stamp = trim($arr[0][0]);
            //如果标记文本中 首个字符是 } 则需要移除这个字符 从这个字符位置处开始重新标记
            if($index_1 = strpos($stamp,'}')!==false){
                //存在 } ，重定义标记文本
                $stamp = substr($stamp,$index_1+1);
            }
//            dump('标记'.$stamp);
            //标记起始位
            $stamp_index = strpos($content_text,$stamp);
            //如果是多行文本注释
            if(strpos($stamp,'*/')!==false){
                $stamp_index = strrpos(substr($content_text,0,$stamp_index),"/**");
            }
            $item_content = '';
            $leftNumber = $rightNumber = 0;//左右{}的数量
            $start = false;
            //根据{}提取文本内容
            for(;$stamp_index<$maxLeng;$stamp_index++){
                if(strpos($item_content,$stamp)!==false){
                    $start = true;
                }
                if($start && $content_text[$stamp_index]=='{'){
                    $leftNumber++;
                }
                if($start && $content_text[$stamp_index]=='}'){
                    $rightNumber++;
                }
                $item_content .= $content_text[$stamp_index];
                if($leftNumber>0 && $rightNumber==$leftNumber){
                    break;//左右一致 并且有标记位 停止检索
                }
            }
            $new_function[] = $item_content;
        }

//        dump($new_function);exit;
        return join("\r\n\r\n",$new_function);
    }

    private function isAddFunctionItem($path,$functions,$nameSpace='app\admin\controller'){
        $AddFunction = [];
//        dump($path);
        if(file_exists($path)){
            //检查控制器 是否有新增方法
            $className = $nameSpace.explode('.',basename($path))[0];
            $ref = new \ReflectionClass($className);
            $action = $ref->getMethods();
//            dump($action);
            foreach ($action as $k=>$v){
                if($v->class == $className){
                    $len = strlen($v->name)-4;
                    if(!in_array($v->name,$functions) && !(strpos($v->name,"get") === 0 && strpos($v->name,"Attr")==$len)){
                        $AddFunction[] = $v->name;
                    }
                }
            }

            //类成员对象
            $properties = $ref->getProperties();
            $AddProperties = [];
            foreach ($properties as $k=>$v){
                if($v->class == $className) {
                    $len = strlen($v->name)-4;
                    if($v->name!='name' && strpos($v->name,'List')!=$len)
                    $AddProperties[] = $v->name;
                }
            }
        }

        return ['function'=>$AddFunction,'proper'=>$AddProperties];
    }

    //添加路由管理
    private function addRoute($moduleInfo){
        $file_name = $moduleInfo['file_name'];
        $moduleName = $moduleInfo['name'];
        $names = "admin/{$file_name}/index";
        $model = new AuthRule();
        $routerIndex = $model->where(['name'=>$names])->find();
        if(empty($routerIndex)){
            $pid = $this->addAuth(0,$names,$moduleName);
        }else{
            $pid = $routerIndex['id'];
            $model->where('id',$pid)->update(['title'=>$moduleName]);
        }
        //编辑
        if(!$model->where(['name'=>"admin/{$file_name}/edit"])->count()){
            $this->addAuth($pid,"admin/{$file_name}/edit","编辑");
        }
        //删除
        if(!$model->where(['name'=>"admin/{$file_name}/delete"])->count()){
            $this->addAuth($pid,"admin/{$file_name}/delete","删除");
        }
    }

    //移除路由功能
    private function delRoute($moduleInfo){
        $file_name = $moduleInfo['file_name'];
        $model = new AuthRule();
        $model->where(['name'=>"admin/{$file_name}/index"])->delete();
        $model->where(['name'=>"admin/{$file_name}/edit"])->delete();
        $model->where(['name'=>"admin/{$file_name}/delete"])->delete();
    }




    private function addAuth($pid,$name,$title,$sort=999){
        $data = [
            'pid'=>$pid,
            'name'=>$name,
            'title'=>$title,
            'sort'=>$sort,
            'is_menu'=>$pid==0?1:0,
        ];
        return (new AuthRule())->insertGetId($data);
    }

    //文件输出 output-->
    protected function outputFile($moduleInfo,$fileAll){

        $config = config('database');
        $config = $config['connections'][$config['default']];
        //表前缀
        $prefix = $config['prefix'];

        //输出控制器
        if($moduleInfo['is_model']!=1 && (!is_array($this->coverList) || $this->coverList['controller']==1) ){
            $this->outputFileItem1($moduleInfo,$fileAll);
        }

        //输出模型文件
        if((!is_array($this->coverList) || $this->coverList['model']==1) ){
            $this->outputFileItem2($moduleInfo,$fileAll,$prefix);
        }

        //输出模板文件
        if($moduleInfo['is_model']!=1  && (!is_array($this->coverList) || $this->coverList['html']==1) ){
            $this->outputFileItem3($moduleInfo,$fileAll,$prefix);
        }

        return true;
    }

    //文件输出 outputapi-->
    protected function outputFileApi($moduleInfo,$fileAll){
        $config = config('database');
        $config = $config['connections'][$config['default']];
        //表前缀
        $prefix = $config['prefix'];

        //输出api控制器
        if(!is_array($this->coverList) || $this->coverList['controller']==1){
            $this->outputFileApiItem1($moduleInfo,$fileAll);
        }
        //输出api服务
        if(!is_array($this->coverList) || $this->coverList['service']==1) {
            $this->outputFileApiItem2($moduleInfo,$fileAll);
        }
        //输出api验证器
        if(!is_array($this->coverList) || $this->coverList['validate']==1) {
            $this->outputFileApiItem3($moduleInfo,$fileAll);
        }

    }

    //输出api控制器
    protected function outputFileApiItem1($moduleInfo,$fileAll){
        $controllerTpl = file_get_contents(self::$file_tpl . '\api\controller.php');
        //状态变量
//        $statusList = $this->getControllerStatusList($moduleInfo['file_name'],$moduleInfo['field_text']);
        //获取器输出
//        $attrList = $this->getControllerAttrList($moduleInfo['field_text']);
        $showdocList = $this->getShowdocText($moduleInfo['field_text']);
        $search = ['[文件名]','[模块名]','[数据注释]','[新增参数]','[返回字段注释]','[新代码插槽]'];
        $replace = [
            ucfirst($moduleInfo['file_name']),
            $moduleInfo['name'],
            $showdocList['数据注释'],
            $showdocList['新增参数'],
            $showdocList['返回字段注释'],
            $this->newCode['controller'],
        ];

        $controllerTpl = str_replace($search,$replace,$controllerTpl);
        // 文件内容替换
        mkdirs(dirname($fileAll['controller'][0]));
        @file_put_contents($fileAll['controller'][0], $controllerTpl);
    }

    //输出api服务
    protected function outputFileApiItem2($moduleInfo,$fileAll){
        $serviceTpl = file_get_contents(self::$file_tpl . '\api\service.php');
        //获取器输出 列表
        $attrList = $this->getControllerAttrList($moduleInfo['field_text']);

        $attrList2 = $this->getControllerAttrList($moduleInfo['field_text'],false);
        $search = ['[文件名]','[模块名]','[获取器输出]','[获取器输出2]','[新代码插槽]'];
        $replace = [
            ucfirst($moduleInfo['file_name']),
            $moduleInfo['name'],
            $attrList,
            $attrList2,
            $this->newCode['service'],
        ];
        //循环创建目录
        mkdirs(dirname($fileAll['service'][0]));
        $serviceTpl = str_replace($search,$replace,$serviceTpl);
        // 文件内容替换
        @file_put_contents($fileAll['service'][0], $serviceTpl);
    }

    protected function outputFileApiItem3($moduleInfo,$fileAll){
        $validateTpl = file_get_contents(self::$file_tpl . '\api\validate.php');

        $ruleText = $this->getServiceRuleList($moduleInfo['field_text']);
        //'id|ID' => 'require',

        $search = ['[文件名]','[rule字段]','[scene字段]'];
        $replace = [
            ucfirst($moduleInfo['file_name']),$ruleText['rule'],$ruleText['scene'],
        ];

        $validateTpl = str_replace($search,$replace,$validateTpl);
        mkdirs(dirname($fileAll['validate'][0]));
        // 文件内容替换
        @file_put_contents($fileAll['validate'][0], $validateTpl);
    }

    //生成showdoc文档信息
    protected function getShowdocText($data){
        $text = [];
        $addParams = [];
        $reData = [];
        foreach ($data as $k=>$v){
            $text[]="\"{$v['field']}\":\"{$v['name']}\"";
            $type = strpos($v['type'],'int')!==false ? 'int':'string';
            $addParams[]="     * @param {$v['field']} 必选 {$type} {$v['name']} ";
            $reData []= "     * @return_param {$v['field']} {$type} {$v['name']}";
        }
//        exit;
//        [返回字段注释]
        return [
            '数据注释'=>join(',',$text),
            '新增参数'=>join("\r\n",$addParams),
            '返回字段注释'=>join("\r\n",$reData),
        ];
    }

    protected function getServiceRuleList($data){
        $text = '';
        $field = [];
        if(empty($data)){
            return [
                'rule'=>'',
                'scene'=>'',
            ];
        }
        foreach ($data as $k=>$v){
            if($v['is_time'])continue;
            $limitWhere = 'require';
            //数字类型
            if(strpos($v['type'],'int')!==false){
                $limitWhere.="|int";
            }
            //图片
            if($v['field_type']==6){
                $limitWhere.="|url";
            }
            $text.="'{$v['field']}|{$v['name']}' => '{$limitWhere}',\r\n";
            $field[] = "'{$v['field']}'";
        }
        return [
            'rule'=>$text,
            'scene'=>join(',',$field),
        ];
    }

    //输出控制器
    protected function outputFileItem1($moduleInfo,$fileAll){
        $controllerTpl = file_get_contents(self::$file_tpl . 'controller.php');
        //状态变量
        $statusList = $this->getControllerStatusList($moduleInfo['file_name'],$moduleInfo['field_text']);
        //获取器输出
        $attrList = $this->getControllerAttrList($moduleInfo['field_text']);
        $multipleList = $this->getContollerMultiple($moduleInfo['field_text']);

        $search = ['[文件名]','[模块名]','[状态变量]','[获取器输出]','[复选框字段输入]','[复选框字段输出]','[breadcrumb]','[新代码插槽]'];
        $replace = [
            ucfirst($moduleInfo['file_name']),
            $moduleInfo['name'],
            $statusList,
            $attrList,
            $multipleList['import'],//复选框解析
            $multipleList['output'],//复选框解析
            $moduleInfo['is_edit_new']==1 ? "'breadcrumb'=>AuthRule::getBreadCid(\$this->request),\r\n" : '',
            $this->newCode['controller'],
        ];

        $controllerTpl = str_replace($search,$replace,$controllerTpl);
//        dump($controllerTpl);exit;
        // 文件内容替换
        @file_put_contents($fileAll['controller'][0], $controllerTpl);
    }

    //生成模型
    protected function outputFileItem2($moduleInfo,$fileAll,$prefix){
        $modelTpl = file_get_contents(self::$file_tpl . 'model.php');
        $search = ['[文件名]','[模块名]','[表名]','[条件查询]','[表字段别名]','[表字段状态]','[导出解释器]','[新代码插槽]'];
        $getWhereTpl = $this->getModelTpl($moduleInfo['field_text']);
        $replace = [
            ucfirst($moduleInfo['file_name']),
            $moduleInfo['name'],
            str_replace($prefix,'',$moduleInfo['table_name']),
            $getWhereTpl['[条件查询]'],
            $getWhereTpl['[表字段别名]'],
            $getWhereTpl['[表字段状态]'],
            $getWhereTpl['[导出解释器]'],
            $this->newCode['model'],
        ];
        $modelTpl = str_replace($search,$replace,$modelTpl);
        @file_put_contents($fileAll['model'][0], $modelTpl);
    }

    //输出视图文件
    protected function outputFileItem3($moduleInfo,$fileAll,$prefix){
        $html_file_name = $fileAll['html_file_name'];

        $search = ['[文件夹名]','[模块名]','[列表字段组]','[模版列表组]','[条件查询组]','[编辑表单组]','[width]','[height]'];
        $getViewTpl = $this->getViewTpl($moduleInfo['field_text']);
        $replace = [
            $html_file_name,
            $moduleInfo['name'],
            $getViewTpl['列表字段组'],
            $getViewTpl['模版列表组'],
            $getViewTpl['条件查询组'],
            $getViewTpl['编辑表单组'],
            $getViewTpl['弹窗宽高']['w'],
            $getViewTpl['弹窗宽高']['h'],
        ];
        if($moduleInfo['is_edit_new']==1){
            //新页面编辑
            $search = array_merge($search,['//[window.open]','[xn_ajax2]','[edit_extend]']);
            $replace = array_merge($replace,['window.open','xn_ajax','main']);
        }else{
            //窗口编辑
            $search = array_merge($search,['//[ajax_open]','[xn_ajax2]','[edit_extend]']);
            $replace = array_merge($replace,['ajax_open','xn_ajax2','iframe']);
        }
        //视图文件 文件夹名
        foreach ($fileAll['html'] as $k=>$v){
            $file = explode('.',basename($v))[0];

            $viewTpl = file_get_contents(self::$file_tpl.'html_' . $file.'.php');
            //文件替换 内容处理
            $viewTpl = str_replace($search,$replace,$viewTpl);
            $view_path = dirname($v);
            !is_dir($view_path) && @mkdir($view_path);
            @file_put_contents($v, $viewTpl);
        }
    }

    //多选框 转换
    private function getContollerMultiple($data){
        $code_text = '';//输入
        $code_text2 = '';//输出
        foreach ($data as $k=>$v){
            if(in_array($v['field_type'],[4])){
                $code_text.="            if(\$param['{$v['field']}']) \$param['{$v['field']}'] = join(',',\$param['{$v['field']}']);\r\n";
                $code_text2.="                \$data->{$v['field']}=explode(',',\$data->{$v['field']});\r\n";
            }
        }
        return [
            'import'=>$code_text,
            'output'=>$code_text2,
        ];
    }
    //获取器输出
    private function getControllerAttrList($data,$isList=true){
        $code_text = '';
        foreach ($data as $k=>$v){
            // 单选 复选 下拉
            if(in_array($v['field_type'],[3,4,5]) || $v['is_time']==1){
//                $code_text.="                \$list[\$k]['{$v['field']}_text'] = \$v->{$v['field']}_text;\r\n";
                $code_text.="                \$v->{$v['field']}_text.='';\r\n";
            }
        }
        if($code_text){
            if($isList){
                $code_text = "foreach (\$list as \$k=>\$v){\r\n".$code_text."            }";
            }else{
                $code_text = str_replace("v->","data->",$code_text);
            }
        }
        return $code_text;
    }

    //获取控制器视图变量
    private function getControllerStatusList($moduleName,$data){
        $code_text = '';
        foreach ($data as $k=>$v){
            if(is_array($v['field_default']) && count($v['field_default'])>0){
                $code_text.= "'{$v['field']}List'=>{$moduleName}Model::\${$v['field']}List,\r\n            ";
            }
        }
        return $code_text;
    }
    //获取模版视图变量
    private function getViewTpl($data){
        $reData = [
            '列表字段组'=>$this->getViewFieldList($data),
            '模版列表组'=>$this->getViewTplList(),
            '条件查询组'=>$this->getViewWhereList($data),
            '编辑表单组'=>$this->getViewEditList($data),
            '弹窗宽高'=>$this->getViewOpenWH($data),
        ];
        return $reData;
    }

    //自动计算弹窗宽高
    private function getViewOpenWH($data){
        $w = 650; $h = 0;

        //普通框  55   图片框  185   富文本框 300
        foreach ($data as $k=>$v){
            if(in_array($v['field_type'],[6,7])){
                $h+=185;
            }else if(in_array($v['field_type'],[8])){
                $h+=300;
                $w = 1000;
            }else{
                $h+=55;
            }
        }
        $h+=50;
        if($h<450){
            $h = 450;
        }
        if($h>800){
            $h = 800;
        }
        return [
            'w'=>$w,
            'h'=>$h,
        ];
    }

    //编辑模版生成
    private function getViewEditList($data){
        $tplList = [
            '1'=>'textTpl',//文本框
            '2'=>'checkbox1Tpl',//开关
            '3'=>'radioTpl',//单选
            '4'=>'checkbox2Tpl',//复选
            '5'=>'selectTpl',//下拉
            '6'=>'imageTpl',//单图
            '7'=>'imagesTpl',//多图
            '8'=>'textareaTpl',//富文本
            '9'=>'textTpl',//锁定
        ];
        //文本框
        $textTpl = <<<text
<div class="layui-form-item">
            <label class="layui-form-label">[name]</label>
            <div class="layui-input-inline">
                <input type="text" name="[field]" lay-verify="required" placeholder="" autocomplete="off" class="layui-input" value="{\$data.[field]}">
            </div>
            <div class="layui-form-mid layui-word-aux"></div>
        </div>
text;
        //开关
        $checkbox1Tpl = <<<text
    <div class="layui-form-item">
        <label class="layui-form-label">[name]</label>
        <div class="layui-input-inline">
            <input type="hidden" name="[field]" value="0">
            <input type="checkbox" lay-verify="required" lay-filter="[field]" name="[field]" lay-skin="switch" lay-text="开|关" value="1" {if \$data[[field]] ==1 }checked{/if}  >
        </div>
        <div class="layui-form-mid layui-word-aux"></div>
    </div>
text;
        //单选框
        $radioTpl = <<<text
  <div class="layui-form-item">
    <label class="layui-form-label">[name]</label>
    <div class="layui-input-block">
     {foreach name="[field]List" item="vo" key="key"}
      <input type="radio" name="[field]" value="{\$key}" title="{\$vo}" {if \$data[[field]] ==\$key }checked{/if} >
      {/foreach}
    </div>
  </div>
text;

        //复选框
        $checkbox2Tpl = <<<text
        <div class="layui-form-item">
            <label class="layui-form-label">[name]</label>
            <div class="layui-input-block">
            {foreach name="[field]List" item="vo" key="key"}
             <input type="checkbox" name="[field][]" value="{\$key}" title="{\$vo}" {if in_array(\$key,\$data[[field]]) }checked{/if} >
            {/foreach}
            </div>
            <div class="layui-form-mid layui-word-aux"></div>
        </div>
text;

        //选择框
        $selectTpl = <<<text
        <div class="layui-form-item">
            <label class="layui-form-label">[name]</label>
            <div class="layui-input-inline">
                <select name="[field]" lay-verify="required">
                    <option value="请选择[name]"></option>
                    {foreach name="[field]List" item="vo" key="key"}
                     <option value="{\$key}" {if \$data[[field]] ==\$key }selected{/if} >{\$vo}</option>
                    {/foreach}
                </select>
            </div>
            <div class="layui-form-mid layui-word-aux"></div>
        </div>
text;

        //文本域
        $textareaTpl = <<<text
        <div class="layui-form-item layui-form-text">
            <label class="layui-form-label">[name]</label>
            <div class="layui-input-block">
                {:xn_ueditor('[field]',\$data.[field])}
            </div>
        </div>
text;

        //单图
        $imageTpl = <<<text
        <div class="layui-form-item layui-form-text">
            <label class="layui-form-label">[name]</label>
            <div class="layui-input-block">
                {:xn_upload_one(\$data.[field],'[field]')}
            </div>
        </div>
text;
        //多图
        $imagesTpl = <<<text
        <div class="layui-form-item layui-form-text">
            <label class="layui-form-label">[name]</label>
            <div class="layui-input-block">
                {:xn_upload_multi(\$data.[field],'[field]')}
            </div>
        </div>
text;

        $code_text = '';
        foreach ($data as $k=>$v){
            if($v['is_edit']!=1 || $v['field']=='id') continue;
            $names =  $tplList[$v['field_type']];
            $TplText = $$names;
            $search = ['[name]','[field]'];
            $replace=[$v['name'],$v['field']];
            $code_text.= str_replace($search,$replace,$TplText)."\r\n";
        }
        return $code_text;
    }
    //条件查询模版 生成
    private function getViewWhereList($data){
        $timeTpl = <<<text

        <div class="layui-inline">
            <!--开始时间-->
            <div class="layui-input-inline">
                <input type="text" name="[name]" id="date_range_box" value="" placeholder="按[value]查询" autocomplete="off" class="layui-input " >
            </div>
        </div>

text;
        $statueTpl = <<<text

        <div class="layui-inline">
            <select name="[name]" lay-verify="required" >
                <option value="">请选择[value]</option>
                {foreach name="[nameAll]" item="vo" key="key"}
                    <option value="{\$key}"  >{\$vo}</option>
                {/foreach}
            </select>
        </div>

text;
        $code_text = '';
        foreach ($data as $k=>$v){
            if($v['show_list']!=1) continue;
            if($v['is_time']==1){
                $search = ['[name]','[value]'];
                $replace=[$v['field'],$v['name']];
                $code_text.= str_replace($search,$replace,$timeTpl)."\r\n\r\n";
            }else if(in_array($v['field_type'],[3,4,5,9])){
                $search = ['[name]','[value]','[nameAll]'];
                $replace=[$v['field'],$v['name'],$v['field'].'List'];
                $code_text.= str_replace($search,$replace,$statueTpl)."\r\n\r\n";
            }
        }
        return $code_text;
    }

    //模版生成
    private function getViewTplList(){
        //开关
        $switchTpl = <<<text
        
<script type="text/html" id="[id]">
    <input type="checkbox" name="[name]" value="{{d.id}}" data-value="[value]" lay-skin="switch" lay-text="[text]" lay-filter="switchTpl" {{ d.[name] == [value1] ? 'checked' : '' }}>
</script>

text;
        //锁定
        $checkboxTpl = <<<text

<script type="text/html" id="[id]">
    <input type="checkbox" name="[name]" value="{{d.id}}" title="禁止" lay-filter="switchTpl" {{ d.[name] == [value1] ? 'checked' : '' }}>
</script>

text;

        //头像
        $imageTpl = <<<text
<!--头像模板-->
<script type="text/html" id="[id]">
    <img class="head_img" src="{{ d.[name]}}" onerror="this.src='/static/admin/images/notpic.png';this.title='无图片'">
</script>
text;


        $code_text = '';
        foreach ($this->tpls as $k=>$item){
            if($k=='switch'){
                $tpl =$switchTpl;
            }else if($k=='checkbox'){
                $tpl = $checkboxTpl;
            }else if($k=='image'){
                $tpl = $imageTpl;
            }else{
                $tpl = '';
            }
            if($tpl){
                foreach ($item as $ks=>$vs){
                    if($k =='checkbox'){
                        $vs = $this->strRollingOver($vs);
                    }
                    $search = ['[id]','[name]','[value]','[text]','[value1]'];
                    $replace=[$vs['id'],$vs['name'],$vs['value'],$vs['text'],$vs['valueArr'][0]];
                    $code_text.= str_replace($search,$replace,$tpl)."\r\n\r\n";
                }
            }
        }
        return $code_text;
    }

    //类似于  0 禁用  1 启用的 这种情况 就会导致出现需要翻转的
//    private function strRollingOver($data){
//        if($data['valueArr'][0] ==0 && $data['valueArr'][1]==1){
//
//        }
//    }

    //视图 获取列表字段组
    // field_type 1 文本 2 开关 3 单选 4 复选 5下拉 6单图 7 多图 8富文本 9 锁定
    private function getViewFieldList($data){
        $field = [];
        $field[] = ['type'=>'checkbox'];

        //列表中 存在的几种模版
        $tpls = [
            //开关
            'switch'=>[],
            //锁定
            'checkbox'=>[],
            //下拉列表
            'select'=>[],
            'image'=>[],//图片
        ];
        foreach ($data as $k=>$v){
            if(!$v['show_list']) continue;
            $item = [
                'field'=>$v['field'],
                'title'=>$v['name'],
            ];

            //宽度自动计算
            if(in_array($v['field_type'],[2,3,6])){
                $item['width'] = 100;
            }
            if($v['field']=='id'){
                $item['width'] = 80;
                $item['sort'] = true;//开启排序
            }
            if($v['is_time']==1){
                $item['width'] = 180;
            }


            //使用获取器 获取
            if(in_array($v['field_type'],[3,4,5]) || $v['is_time']==1){
                $item['field'].="_text";
                $item['sort'] = true;
            }
            //开关 or 锁定按钮
            if(in_array($v['field_type'],[2,9])){
                $item['sort'] = true;
                $type = $v['field_type'] ==2 ? 'switch': 'checkbox';
                $count = count($v['field_default']);
                $field_default = $v['field_default'];

                if($count>2){
                    $field_default = array_slice($v['field_default']);
                }else if($count<2){
                    $field_default = [
                        '1'=>'正常',
                        '0'=>'禁用',
                    ];
                }
                $id =$type.ucfirst($v['field']).'Tpl';
                $tpls[$type][] = [
                    'id'=>$id,
                    'name'=>$v['field'],
                    'value'=>join('|',array_keys($field_default)),
                    'text'=>join('|',array_values($field_default)),
                    'valueArr'=>array_keys($field_default),
                ];
                $item['templet'] = '#'.$id;
            }else if($v['field_type'] == 5){
                //下拉
                $id ='select'.ucfirst($v['field']).'Tpl';
                $field_default = $v['field_default'];
                $tpls['select'][] = [
                    'id'=>$id,
                    'name'=>$v['field'],
                    'value'=>$field_default,
                ];
                $item['templet'] =  '#'.$id;
            }else if($v['field_type']==6){
                //单图上传
                $id ='image'.ucfirst($v['field']).'Tpl';
                $field_default = $v['field_default'];
                $tpls['image'][] = [
                    'id'=>$id,
                    'name'=>$v['field'],
                    'value'=>$field_default,
                ];
                $item['templet'] =  '#'.$id;
            }
            $field[] = $item;
        }
        //增加编辑按钮
        $field[] = [
            'title'=>'操作',
            'templet'=>'#apiListBar',
            'width'=>200,
        ];
        //序列化 转换为js代码格式
        $code_text = str_replace(['},','[{','}]','{"'],["},\r\n","[\r\n{","}\r\n        ]",'            {"'],json_encode($field,320));

        //生成 text/html 模版
        $this->tpls = $tpls;

        return $code_text;
    }

    private function getModelTpl($data){
        $data = [
            '[条件查询]'=>$this->getWhereTpl($data),
            '[表字段别名]'=>$this->getTableFieldAlias($data),
            '[表字段状态]'=>$this->getTableFieldStatus($data),
            '[导出解释器]'=>$this->getTableFieldSAttr($data),
        ];
        return $data;
    }

    //导出字段解析器
    private function getTableFieldSAttr($data){
        $code_text = '';
        foreach ($data as $k=>$v){
            if(in_array($v['field_type'],[2,3,4,5])){
                $code_text.="            \$list[\$k]['{$v['field']}'] = \$v->{$v['field']}_text;\r\n";

            }
            if($v['is_time']==1){
                $code_text.="            if(is_numeric(\$v->{$v['field']}))\$list[\$k]['{$v['field']}'] = \$v->{$v['field']}_text;\r\n";
            }
        }
        return $code_text;
    }

    //根据表默认字段返回字段状态
    private function getTableFieldStatus($data){
        $code_text = '';
        $jiexiTpl = <<<text
    //[name]获取器
    public function get[field2]TextAttr(\$value,\$data){
        if(strpos(\$data['[field]'],',')){
            \$arr = explode(',',\$data['[field]']);
            \$arrText = [];
            foreach (\$arr as \$v){
                \$arrText[]=self::\$[field]List[\$v];
            }
            return join(',',\$arrText);
        }else{
            return self::\$[field]List[\$data['[field]']]?:'--';
        }
    }
text;

        $timeTpl = <<<text
    public function get[field2]TextAttr(\$value,\$data){
        if(is_numeric(\$data['[field]'])){
            return \$data['[field]']>0 ? date(self::\$formatTime,\$data['[field]']) : '--';
        }else{
            return \$data['[field]'];
        }
    }
text;



        foreach ($data as $k=>$v){
            if(strpos($v['field'],'_')){
                $arr = explode("_",$v['field']);
                $field2 = join('',array_map(function($a){return ucfirst($a);},$arr));
            }else{
                $field2 = ucfirst($v['field']);
            }
            if(!in_array($v['field_type'],[1,6,7,8]) && is_array($v['field_default']) && count($v['field_default'])>0){
                $field_default = $v['field_default'];
                //开始转换
                $item_code_text = '    public static $'.$v['field'].'List = ['."\r\n";

                foreach ($field_default as $ks=>$vs){
                    $item_code_text.="            '{$ks}'=>'{$vs}',\r\n";
                }
                $item_code_text .= "    ];\r\n\r\n";

                //开关  单选  复选 都需要解析器
                if(in_array($v['field_type'],[2,3,4,5]))
                    // 增加解析器  ucfirst
                    $item_code_text.= str_replace(['[field]','[name]','[field2]'],[
                            $v['field'],
                            $v['name'],
                            $field2,
                        ],$jiexiTpl)."\r\n\r\n";


                $code_text.= $item_code_text;
            }
            //时间
            if($v['is_time']){
                // 增加解析器
                $item_code_text = str_replace(['[field]','[name]','[field2]'],[
                        $v['field'],
                        $v['name'],
                        $field2,
                    ],$timeTpl)."\r\n\r\n";
                $code_text.= $item_code_text;
            }
        }
        return $code_text;
    }

    //返回字段别名
    private function getTableFieldAlias($data){
        $code_text = 'public static $fieldsList = ['."\r\n";
        $code_tpl = <<<text
            '[field]'=>'[name]',

text;
        foreach ($data as $k=>$v){
            $code_text.=str_replace([
                '[field]','[name]'
            ],[$v['field'],$v['name']],$code_tpl);
        }
        $code_text.="\r\n".'    ];';
        return $code_text;
    }

    //根据表字段 返回列表查询条件语句
    private function getWhereTpl($data){
        $code_text = '';
        //普通条件
        $whereText1 = <<<TEXT
    
        if(\$param['[字段]']){
            \$where['[字段]'] = \$param['[字段]'];
        }

TEXT;
        $whereText2 = <<<TEXT
        
        if( \$param['[字段]']!='' ) {
            \$create_time = explode('至',\$param['[字段]']);
            \$date_time = [
                strtotime(\$create_time[0]),
                strtotime(\$create_time[1].' 23:59:59'),
            ];
            \$model->whereBetween('[字段]',\$date_time);
        }

TEXT;

        foreach ($data as $k=>$v){
            //如果在列表显示 就参与 字段判断
            if($v['show_list']==1){
                $whereText = $v['is_time'] ? $whereText2:$whereText1;
                $code_text.= str_replace('[字段]',$v['field'],$whereText);
            }
        }
        return $code_text;
    }

    //通过文件名 返回所有文件路径
    protected function getFilePath($file_name){
        $controllerPath = ROOT_PATH . self::$namespaces[0];
        $modelPath = ROOT_PATH.self::$namespaces[1];
        $htmlPath = ROOT_PATH.self::$namespaces[2];

        //html 文件夹名字
        $html_file_name = lcfirst($file_name);
        //大写替换为_小写
        $arr = preg_split('/([A-Z])/',lcfirst($html_file_name),-1,PREG_SPLIT_DELIM_CAPTURE);
        foreach ($arr as $v){
            if(strlen($v)==1){
                $html_file_name = str_replace($v,'_'.lcfirst($v),$html_file_name);
            }
        }

        $reData = [
            'controller'=>[
                $controllerPath.DS.ucfirst($file_name).'.php',
            ],
            'model'=>[
                $modelPath.DS.ucfirst($file_name).'Model.php',
            ],
            'html'=>[
                //首页
                $htmlPath.DS.$html_file_name.'/index.html',
                //首页搜索
                $htmlPath.DS.$html_file_name.'/index_form.html',
                //首页编辑
                $htmlPath.DS.$html_file_name.'/index_edit.html',
                $htmlPath.DS.$html_file_name.'/index_tpl.html',
            ],
            //视图文件的文件名
            'html_file_name'=>$html_file_name,
        ];
        return $reData;
    }

    //通过文件名 返回所有api文件路径
    protected function getFilePathApi($file_name){
        $controllerPath = ROOT_PATH . self::$namespaces[3];
        $servicePath = ROOT_PATH.self::$namespaces[4];
        $validatePath = ROOT_PATH.self::$namespaces[5];

        $reData = [
            'controller'=>[
                $controllerPath.DS.ucfirst($file_name).'.php',
            ],
            'service'=>[
                $servicePath.DS.ucfirst($file_name).'Service.php',
            ],
            'validate'=>[
                $validatePath.DS.ucfirst($file_name).'.php',
            ],
        ];
        return $reData;
    }

    //检查文件是否存在
    protected function isFileExistence($file_list){
        foreach ($file_list as $item){
            foreach ($item as $k=>$v){
                if(file_exists($v)){
                    return true;
                }
            }
        }
        return false;
    }

}